#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <unistd.h>
#include "icar.h"
#include "icar_parse.h"
#include "icar_msg.h"
#include "icar_end_msg.h"
#include "icar_end_param.h"
#include "icar_log.h"
#include "icar_utils.h"

static int fill_local_info(uint8_t *data, size_t size, struct endLocalInfo *info);
static int combine_pkg(int fd, struct msgRecv *msg);


static int pend_response(uint8_t *data, size_t size, void *arg);
static int pend_heartbeat(uint8_t *data, size_t size, void *arg);
static int pend_register(uint8_t *data, size_t size, void *arg);
static int pend_unregister(uint8_t *data, size_t size, void *arg);
static int pend_auth(uint8_t *data, size_t size, void *arg);
static int pend_paramRes(uint8_t *data, size_t size, void *arg);
static int pend_attrRes(uint8_t *data, size_t size, void *arg);
static int pend_updateNote(uint8_t *data, size_t size, void *arg);
static int pend_local_report(uint8_t *data, size_t size, void *arg);
static int pend_local_response(uint8_t *data, size_t size, void *arg);
static int pend_event_report(uint8_t *data, size_t size, void *arg);
static int pend_askRes(uint8_t *data, size_t size, void *arg);
static int pend_infobc(uint8_t *data, size_t size, void *arg);
static int pend_vehicle_res(uint8_t *data, size_t size, void *arg);
static int pend_data_upload(uint8_t *data, size_t size, void *arg);
static int pend_elec_report(uint8_t *data, size_t size, void *arg);
static int pend_driverId_report(uint8_t *data, size_t size, void *arg);
static int pend_localBulkUpload(uint8_t *data, size_t size, void *arg);
static int pend_can_upload(uint8_t *data, size_t size, void *arg);
static int pend_event_upload(uint8_t *data, size_t size, void *arg);
static int pend_event_data(uint8_t *data, size_t size, void *arg);
static int pend_film_response(uint8_t *data, size_t size, void *arg);
static int pend_store_mediaRep(uint8_t *data, size_t size, void *arg);
static int pend_uplink_trans(uint8_t *data, size_t size, void *arg);
static int pend_compress(uint8_t *data, size_t size, void *arg);
static int pend_rsa_encrypt(uint8_t *data, size_t size, void *arg);

static void hend_response(int rsa, const char *number, void *arg);
static void hend_heartbeat(int rsa, const char *number, void *arg);
static void hend_register(int rsa, const char *number, void *arg);
static void hend_unregister(int rsa, const char *number, void *arg);
static void hend_auth(int rsa, const char *number, void *arg);
static void hend_paramRes(int rsa, const char *number, void *arg);
static void hend_attrRes(int rsa, const char *number, void *arg);
static void hend_updateNote(int rsa, const char *number, void *arg);
static void hend_local_report(int rsa, const char *number, void *arg);
static void hend_local_response(int rsa, const char *number, void *arg);
static void hend_event_report(int rsa, const char *number, void *arg);
static void hend_askRes(int rsa, const char *number, void *arg);
static void hend_infobc(int rsa, const char *number, void *arg);
static void hend_vehicle_res(int rsa, const char *number, void *arg);
static void hend_data_upload(int rsa, const char *number, void *arg);
static void hend_elec_report(int rsa, const char *number, void *arg);
static void hend_driverId_report(int rsa, const char *number, void *arg);
static void hend_localBulkUpload(int rsa, const char *number, void *arg);
static void hend_can_upload(int rsa, const char *number, void *arg);
static void hend_event_upload(int rsa, const char *number, void *arg);
static void hend_event_data(int rsa, const char *number, void *arg);
static void hend_local_report(int rsa, const char *number, void *arg);
static void hend_local_response(int rsa, const char *number, void *arg);
static void hend_film_response(int rsa, const char *number, void *arg);
static void hend_store_mediaRep(int rsa, const char *number, void *arg);
static void hend_uplink_trans(int rsa, const char *number, void *arg);
static void hend_compress(int rsa, const char *number, void *arg);
static void hend_rsa_encrypt(int rsa, const char *number, void *arg);



static void fend_register(void *arg);
static void fend_auth(void *arg);
static void fend_local_report(void *arg);
static void fend_local_response(void *arg);
static void fend_paramRes(void *arg);
static void fend_data_upload(void *arg);
static void fend_elec_report(void *arg);
static void fend_driverId_report(void *arg);
static void fend_localBulkUpload(void *arg);
static void fend_can_upload(void *arg);
static void fend_event_data(void *arg);
static void fend_store_mediaRep(void *arg);
static void fend_uplink_trans(void *arg);
static void fend_compress(void *arg);



struct msg_handle msg_handles[] = {
	{ ICAR_END_RESPONSE, 	pend_response, 	hend_response, NULL},
	{ ICAR_END_HEARTBEAT, 	pend_heartbeat, hend_heartbeat, NULL},
	{ ICAR_END_REGISTER, 	pend_register, 	hend_register, fend_register},
	{ ICAR_END_UNREGISTER, 	pend_unregister, hend_unregister, NULL},
	{ ICAR_END_AUTHENTICATE, pend_auth, hend_auth, fend_auth},
	{ ICAR_END_PARAM_RESPONSE, pend_paramRes, hend_paramRes, NULL },
	{ ICAR_END_ATTR_RES, pend_attrRes, hend_attrRes, NULL},
	{ ICAR_END_UPGRADE_NOTICE, pend_updateNote, hend_updateNote, NULL},
	{ ICAR_END_LOCALINFO_REPORT, pend_local_report, hend_local_report, fend_local_report},
	{ ICAR_END_LOCALINFO_RESPONSE, pend_local_response, hend_local_response, fend_local_response},
	{ ICAR_END_EVENT_REPORT, pend_event_report, hend_event_report, NULL},
	{ ICAR_END_ASK_RESPONSE, pend_askRes, hend_askRes, NULL},
	{ ICAR_END_INFO_HELPMENU_CANCLE, pend_infobc, hend_infobc, NULL},
	{ ICAR_END_VEICHLE_CTL_RESPONSE, pend_vehicle_res, hend_vehicle_res, NULL},
	{ ICAR_END_DATA_RECORDER_UPLOAD, pend_data_upload, hend_data_upload, fend_data_upload},
	{ ICAR_END_ELEC_WAYBILL_REPORT, pend_elec_report, hend_elec_report, fend_elec_report},
	{ ICAR_END_DRIVER_IDINFO_REPORT, pend_driverId_report, hend_driverId_report, fend_driverId_report},
	{ ICAR_END_LOCALDATA_BULK_UPLOAD, pend_localBulkUpload, hend_localBulkUpload, fend_localBulkUpload },
	{ ICAR_END_CAN_DATA_UPLOAD, pend_can_upload, hend_can_upload, NULL },
	{ ICAR_END_MULTMEDIA_EVENT_UPLOAD, pend_event_upload, hend_event_upload, NULL },
	{ ICAR_END_MULTMEDIA_DATA_UPLOAD, pend_event_data, hend_event_data, fend_event_data},
	{ ICAR_END_CAMERA_FILM_RESPONSE, pend_film_response, hend_film_response, NULL},
	{ ICAR_END_STORE_MULTMEDIA_CHECK_RESPONSE, pend_store_mediaRep, hend_store_mediaRep, NULL},
	{ ICAR_END_DATA_UPLINK_TRANSMISSON, pend_uplink_trans, hend_uplink_trans, fend_uplink_trans },
	{ ICAR_END_DATA_COMPRESS_REPORT, pend_compress, hend_compress, fend_compress },
	{ ICAR_END_RSA_ENCRYPT, pend_rsa_encrypt, hend_rsa_encrypt, NULL },
	{ 0, NULL, NULL, NULL}
};


/* 处理终端的通用应答 */
static int
pend_response(uint8_t *data, size_t size, void *arg)
{
	if (size != 5 || !data)
		return -1;

	struct endResponse *res = (struct endResponse *)arg;

	if (res == NULL)
		return -1;

	res->sequence = data[0] << 8 | data[1]; 	/* 对应的平台消息的流水号 */
	res->id = data[2] << 8 | data[3];		/* 对应的平台消息的ID */
	res->result = data[4];				/* 结果: 0:成功/确认; 1: 失败; 2:消息有误 3:不支持*/

	return 0;

}

static  int
pend_heartbeat(uint8_t *data, size_t size, void *arg)
{
	return 0;
}

static int
pend_register(uint8_t *data, size_t size, void *arg)
{
	struct endRegister *reg = (struct endRegister *)arg;

	if ((data == NULL) || size <= 36)
		return -1;

	if (reg == NULL)
		return -1;

	size_t i = 0;
	char *p = NULL;

	reg->province = data[i] << 8 | data[i+1];		/* 省域ID */
	i += 2;
	reg->city = data[i] << 8 | data[i+1];			/* 市县域ID */
	i += 2;
	memcpy(reg->product, &data[i], 5);				/* 制造商ID 5个字节 */
	i += 5;
	memcpy(reg->model, &data[i], 20);			/* 终端型号 20个字节，此终端型号由制造商自行定义，位数不足时，后补0x00 */
	i += 20;
	memcpy(reg->end_id, &data[i], 7);				/* 终端ID */
	i += 7;
	reg->plate_color = data[i++];					/* 车牌颜色 */


	p = (char *)&data[i];
	reg->plate_mark = strdup(p);
	if (reg->plate_mark == NULL)
		return -1;
	if ((strlen(p) + 1) != (size - i)) {
		free(reg->plate_mark);
		reg->plate_mark = NULL;
		return -1;
	}
	return 0;
}

static int
pend_unregister(uint8_t *data, size_t size, void *arg)
{
	return 0;
}

static int
pend_auth(uint8_t *data, size_t size, void *arg)
{
	struct endAuth *auth = (struct endAuth *)arg;
	char *p = (char *)data;
	auth->code = strdup(p);
	if (auth->code == NULL)
		return -1;

	auth->len = strlen(p) + 1;

	if (auth->len != size) {
		free(auth->code);
		auth->code = NULL;
		return -1;
	}
}

/* 解析 查询参数应答 */
static int
pend_paramRes(uint8_t *data, size_t size, void *arg)
{
	struct param_list *param = (struct param_list *)arg;

	if ((data == NULL) || (param == NULL))
		return -1;

	if (size <= 1)
		return -1;

	int i;
	size_t n = 0;
	param->lsize = data[n++] & 0xff;

	for (i = 0; i < param->lsize; i++) {
		if (n + 5 >= size)
			return -1;
		param->list[i].id = data[n] << 24 | data[n+1] << 16 | data[n+2] << 8 | (data[n+3] & 0xff);
		n += 4;
		param->list[i].len = data[n++] & 0xff;
		if (n + param->list[i].len > size)
			return -1;

		switch (param->list[i].id) {
		case 0x0001:
		case 0x0002:
		case 0x0003:
		case 0x0004:
		case 0x0005:
		case 0x0006:
		case 0x0007:
		case 0x0018:
		case 0x0019:
		case 0x0020:
		case 0x0021:
		case 0x0022:
		case 0x0027:
		case 0x0028:
		case 0x0029:
		case 0x002C:
		case 0x002D:
		case 0x002E:
		case 0x002F:
		case 0x0030:
		case 0x0045:
		case 0x0046:
		case 0x0047:
		case 0x0050:
		case 0x0051:
		case 0x0052:
		case 0x0053:
		case 0x0054:
		case 0x0055:
		case 0x0056:
		case 0x0057:
		case 0x0058:
		case 0x0059:
		case 0x005A:
		case 0x0064:
		case 0x0065:
		case 0x0070:
		case 0x0071:
		case 0x0072:
		case 0x0073:
		case 0x0074:
		case 0x0080:
		case 0x0093:
		case 0x0095:
		case 0x0100:
		case 0x0102:
			{
				if (param->list[i].len != 4)
					return -1;

				param->list[i].value.l = data[n] << 24 | data[n+1] << 16 | data[n+2] << 8 | (data[n+3] & 0xff);

				n += 4;
			}
			break;
		case 0x0031:
		case 0x005B:
		case 0x005C:
		case 0x005D:
		case 0x005E:
		case 0x0081:
		case 0x0082:
		case 0x0101:
		case 0x0103:
			{
				if (param->list[i].len != 2)
					return -1;

				param->list[i].value.s = data[n] << 8 | (data[n+1] & 0xff);

				n += 2;
			}
			break;
		case 0x0084:
		case 0x0090:
		case 0x0091:
		case 0x0092:
		case 0x0094:
			{
				if (param->list[i].len != 1)
					return -1;

				param->list[i].value.b = data[n++] & 0xff;
			}
			break;
		case 0x0010:
		case 0x0011:
		case 0x0012:
		case 0x0013:
		case 0x0014:
		case 0x0015:
		case 0x0016:
		case 0x0017:
		case 0x001A:
		case 0x001B:
		case 0x001C:
		case 0x001D:
		case 0x0040:
		case 0x0041:
		case 0x0042:
		case 0x0043:
		case 0x0044:
		case 0x0048:
		case 0x0049:
		case 0x0083:
			{
				memcpy(param->list[i].value.c, &data[n], param->list[i].len);
				n += param->list[i].len;
			}
			break;
		case 0x0110:
		case 0x0111 ... 0x01FF:
			{
				if (param->list[i].len != 8)
					return -1;

				memcpy(param->list[i].value.c, &data[n], param->list[i].len);
				n += 8;
			}
			break;
		default:
			return -1;
		}
	}

	return 0;
}

/* 解析 查询终端属性应答 */
static int
pend_attrRes(uint8_t *data, size_t size, void *arg)
{
	if ((data == NULL) || size <= 55)
		return -1;

	struct endAttr *attr = (struct endAttr *)arg;
	size_t i;

	if (attr == NULL)
		return -1;

	i = 0;
	attr->type = data[i] << 8 | data[i+1];
	i += 2;
	memcpy(attr->product, &data[i], 5);
	i += 5;
	memcpy(attr->model, &data[i], 20);
	i += 20;
	memcpy(attr->endId, &data[i], 7);
	i += 7;
	memcpy(attr->iccid, &data[i], 10);
	i += 10;
	attr->hverLen = data[i++];
	if (attr->hverLen + i >= size)
		return -1;
	memcpy(attr->hversion, &data[i], attr->hverLen);
	i += attr->hverLen;
	if (strlen(attr->hversion) + 1 != attr->hverLen)
		return -1;
	if (i+1 >= size)
		return -1;
	attr->fverLen = data[i++];
	if (attr->fverLen + i >= size)
		return -1;
	memcpy(attr->fversion, &data[i], attr->fverLen);
	i += attr->fverLen;
	if (strlen(attr->fversion) + 1 != attr->fverLen)
		return -1;

	if (i + 2 != size)
		return -1;

	attr->gnss = data[i++];
	attr->communication = data[i];

	return 0;
}

static int
pend_updateNote(uint8_t *data, size_t size, void *arg)
{
	struct endUpdateNote *note = (struct endUpdateNote *)arg;
	if ((data == NULL) || size != 2 || note == NULL)
		return -1;
	note->type = data[0] & 0xff;
	note->type = data[1] & 0xff;
	return 0;
}

static int
pend_local_report(uint8_t *data, size_t size, void *arg)
{
	return 0;
}

static int
pend_local_response(uint8_t *data, size_t size, void *arg)
{
	if ((data == 0) || (size < 30) || (arg == NULL))
		return -1;

	struct localInfoResponse *res = (struct localInfoResponse *)arg;
	size_t i = 0;
	res->sequence = data[i] << 8 | data[i+1];
	i += 2;

	fill_local_info(&data[i], 28, &(res->info));
	i += 28;

	return 0;
}

static int
pend_event_report(uint8_t *data, size_t size, void *arg)
{
	if (data == NULL || (size != 1) || (arg == NULL))
		return -1;
	uint8_t *id = (uint8_t *)arg;

	*id = data[0] & 0xff;
	return 0;
}

static int
pend_askRes(uint8_t *data, size_t size, void *arg)
{
	struct askRes *res = (void *)arg;
	if ((data == NULL) || size != 3 || (res == NULL))
		return -1;

	res->sequence = data[0] << 8 | data[1];
	res->resId = data[2];
	return 0;
}

static int
pend_infobc(uint8_t *data, size_t size, void *arg)
{
	struct infoBC *bc = (struct infoBC *)arg;
	if ((data == NULL) || size != 2 || (bc == NULL))
		return -1;

	bc->type = data[0];
	bc->mark = data[1];

	return 0;
}

static int
pend_vehicle_res(uint8_t *data, size_t size, void *arg)
{
	if ((data == NULL) || (size < 30) || (arg == NULL))
		return -1;
	struct vehicleCtlRes *res = (struct vehicleCtlRes *)arg;
	size_t i = 0;

	res->sequence = data[i] << 8 | data[i+1];
	i += 2;
	fill_local_info(&data[i], 28, &(res->info));
	i += 28;

	return 0;
}

static int
pend_data_upload(uint8_t *data, size_t size, void *arg)
{
	if ((data == NULL) || (size <= 3) || (arg == NULL))
		return -1;
	struct recoderUpload *up = (struct recoderUpload *)arg;
	size_t i;

	i = 0;
	up->sequence = data[i] << 8 | data[i+1];
	i += 2;

	up->cmd = data[i++];

	up->len = size - i;

	up->data = calloc(up->len+1, 1);
	if (up->data == NULL)
		return -1;

	memcpy(up->data, &data[i], up->len);

	return 0;
}

static int
pend_elec_report(uint8_t *data, size_t size, void *arg)
{
	if ((data == NULL) || (size <= 4) || (arg == NULL))
		return -1;

	struct elecWaybillReport *rep = (struct elecWaybillReport *)arg;
	size_t i = 0;

	rep->len = data[i] << 24 | data[i+1] << 16 | data[i+2] << 8 | data[i+3];
	i += 4;
	if (rep->len != (size - 4))
		return -1;

	rep->data = calloc(rep->len+1, 1);
	if (rep->data == NULL)
		return -1;

	memcpy(rep->data, &data[i], rep->len);

	return 0;
}

/* 驾驶员身份信息采集上报 */
static int
pend_driverId_report(uint8_t *data, size_t size, void *arg)
{
	if ((data == NULL) || (size < 30) || (arg == NULL))
		return -1;

	struct driverIdRep *rep = (struct driverIdRep *)arg;
	size_t i;

	i = 0;
	rep->status = data[i++];
	memcpy(rep->tbcd, &data[i], 6);
	i += 6;
	rep->icres = data[i++];
	rep->nlen = data[i++];
	if (i + rep->nlen >= size)
		return -1;
	rep->name = (char *)malloc(rep->nlen+1);
	if (rep->name == NULL)
		return -1;
	memset(rep->name, 0, rep->nlen+1);
	memcpy(rep->name, &data[i], rep->nlen);
	i += rep->nlen;

	if (i + 20+1 >= size)
	{
		goto rep_error1;
	}

	memcpy(rep->certification, &data[i], 20);
	i += 20;

	rep->orgarlen = data[i++];
	if (i + rep->orgarlen >= size)
	{
		goto rep_error1;
	}

	rep->organization = (char *)malloc(rep->orgarlen + 1);
	if (rep->organization == NULL)
		goto rep_error1;
	memset(rep->organization, 0, rep->orgarlen + 1);
	memcpy(rep->organization, &data[i], rep->orgarlen);
	i += rep->orgarlen;

	if (i + 4 > size)
		goto rep_error2;

	memcpy(rep->validaty, &data[i], 4);

	return 0;

rep_error2:
	free(rep->organization);
	rep->organization = NULL;

rep_error1:
	free(rep->name);
	rep->name = NULL;
	return -1;
}

static int
pend_localBulkUpload(uint8_t *data, size_t size, void *arg)
{
	return 0;
}


static int
pend_can_upload(uint8_t *data, size_t size, void *arg)
{
	if ((data == NULL) || (size < 8) || (arg == NULL))
		return -1;

	struct canUpload *can = (struct canUpload *)arg;
	size_t i;
	int count;

	i = 0;
	can->count = data[0] << 8 | data[1];
	i += 2;
	memcpy(can->rtime, &data[i], 5);
	i += 5;

	if ((i + can->count * 12) != size)
		return -1;

	for (count = 0; count < can->count; count++) {
		memcpy(can->d[count].id, &data[i], 4);
		i += 4;
		memcpy(can->d[count].data, &data[i], 8);
		i += 8;
	}

	return 0;
}

static int
pend_event_upload(uint8_t *data, size_t size, void *arg)
{
	if ((data == NULL) || (size != 7) || (arg == NULL))
		return -1;

	struct mediaEvent *event = (struct mediaEvent *)arg;
	event->id = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
	event->type = data[4];
	event->event = data[5];
	event->channel = data[6];
	return 0;
}

static int
pend_event_data(uint8_t *data, size_t size, void *arg)
{
	if ((data == NULL) || (size < 36) || (arg == NULL))
		return -1;

	struct mediaData *da = (struct mediaData *)arg;
	size_t i;

	i = 0;
	da->id = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
	i += 4;
	da->type = data[i++];
	da->format = data[i++];
	da->event = data[i++];
	da->channel = data[i++];
	fill_local_info(&data[i], 28, &(da->local));
	i += 28;
	da->len = size - i;
	da->data = (uint8_t *)malloc(da->len + 1);
	if (da->data == NULL)
		return -1;
	memset(da->data, 0, da->len + 1);
	memcpy(da->data, &data[i], da->len);

	return 0;
}

static int
pend_film_response(uint8_t *data, size_t size, void *arg)
{
	if ((data == NULL) || (size != 5) || (arg == NULL))
		return -1;

	struct cameraFilmRes *res = (struct cameraFilmRes *)arg;
	res->sequence = data[0] << 8 | data[1];
	res->result = data[2];
	res->count = data[3] << 8 | data[4];

	return 0;
}

static int
pend_store_mediaRep(uint8_t *data, size_t size, void *arg)
{
	if ((data == NULL) || (size <= 4) || (arg == NULL))
		return -1;

	size_t i;
	struct storeMediaRep *rep = (struct storeMediaRep *)arg;
	int n;

	i = 0;
	rep->sequence = data[i] << 8 | data[i+1];
	i += 2;
	rep->total = data[i] << 8 | data[i+1];
	i += 2;

	if ((i + rep->total * 34) != size)
		return -1;

	for (n = 0; n < rep->total; n++) 
	{
		rep->op[i].id = data[i] << 24 | data[i+1] << 16 | data[i+2] << 8 | data[i+3];
		i += 4;
		rep->op[i].type = data[i++];
		rep->op[i].channel = data[i++];
		rep->op[i].format = data[i++];
		fill_local_info(&data[i], 28, &(rep->op[i].local));
		i += 28;
	}

	return 0;
}

static int
pend_uplink_trans(uint8_t *data, size_t size, void *arg)
{
	if ((data == NULL) || (arg == NULL))
		return -1;

	struct dataUpTrans *trans = (struct dataUpTrans *)arg;
	if (size <= 1)
		return -1;

	trans->type = data[0];
	trans->len = size -1;
	trans->data = (uint8_t *)malloc(trans->len+1);
	if (trans->data == NULL)
		return -1;
	memset(trans->data, 0, trans->len+1);

	memcpy(trans->data, &data[1], trans->len);

	return 0;
}

static int
pend_compress(uint8_t *data, size_t size, void *arg)
{
	if ((data == NULL) || (arg == NULL))
		return -1;

	if (size <= 4)
		return -1;

	struct dataCompress *com = (struct dataCompress *)arg;

	com->len = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
	if (com->len != (size - 4))
		return -1;
	com->data = (uint8_t *)calloc(com->len+1, 1);
	if (com->data == NULL)
		return -1;

	memcpy(com->data, &data[4], com->len);
	return 0;
}

static int
pend_rsa_encrypt(uint8_t *data, size_t size, void *arg)
{
	if ((data == NULL) || (size != 132) || (arg == NULL))
		return -1;

	struct endRsaEncrypt *rsa = (struct endRsaEncrypt *)arg;

	rsa->e = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];

	memcpy(rsa->n, &data[4], 128);

	return 0;
}


static void
hend_response(int rsa, const char *number, void *arg)
{
}

static void
hend_heartbeat(int rsa, const char *number, void *arg)
{
}

static void
hend_register(int rsa, const char *number, void *arg)
{
}

static void
hend_unregister(int rsa, const char *number, void *arg)
{
}

static void
hend_auth(int rsa, const char *number, void *arg)
{
}

static void
hend_paramRes(int rsa, const char *number, void *arg)
{
}

static void
hend_attrRes(int rsa, const char *number, void *arg)
{
}


static void
hend_updateNote(int rsa, const char *number, void *arg)
{
}

static void
hend_local_report(int rsa, const char *number, void *arg)
{
}

static void
hend_local_response(int rsa, const char *number, void *arg)
{
}

static void
hend_event_report(int rsa, const char *number, void *arg)
{
}

static void
hend_askRes(int rsa, const char *number, void *arg)
{
}

static void
hend_infobc(int rsa, const char *number, void *arg)
{
}

static void
hend_vehicle_res(int rsa, const char *number, void *arg)
{
}

static void
hend_data_upload(int rsa, const char *number, void *arg)
{
}

static void
hend_elec_report(int rsa, const char *number, void *arg)
{
}

static void
hend_driverId_report(int rsa, const char *number, void *arg)
{
}

static void
hend_localBulkUpload(int rsa, const char *number, void *arg)
{
}

static void
hend_can_upload(int rsa, const char *number, void *arg)
{
}

static void
hend_event_upload(int rsa, const char *number, void *arg)
{
}

static void
hend_event_data(int rsa, const char *number, void *arg)
{
}

static void
hend_film_response(int rsa, const char *number, void *arg)
{
}

static void
hend_store_mediaRep(int rsa, const char *number, void *arg)
{
}

static void
hend_uplink_trans(int rsa, const char *number, void *arg)
{
}

static void
hend_compress(int rsa, const char *number, void *arg)
{
}

static void
hend_rsa_encrypt(int rsa, const char *number, void *arg)
{
}



static void
fend_register(void *arg)
{
	struct endRegister *reg = (struct endRegister *)arg;

	if (reg == NULL)
		return;

	if (reg->plate_mark)
	{
		free(reg->plate_mark);
		reg->plate_mark = NULL;
		return;
	}
}

static void
fend_auth(void *arg)
{
	struct endAuth *auth = (struct endAuth *)arg;

	if (auth == NULL)
		return;

	if (auth->code) {
		free(auth->code);
		auth->code = NULL;
	}
}

static void
fend_local_report(void *arg)
{
}

static void
fend_local_response(void *arg)
{
}

static void
fend_data_upload(void *arg)
{
	struct recoderUpload *up = (struct recoderUpload *)arg;

	if (up == NULL)
		return ;

	if (up->data)
	{
		free(up->data);
		up->data = NULL;
	}
}

static void 
fend_elec_report(void *arg)
{
	struct elecWaybillReport *elec = (struct elecWaybillReport *)arg;
	if (elec == NULL)
		return;

	if (elec->data)
	{
		free(elec->data);
		elec->data = NULL;
	}
}

static void
fend_driverId_report(void *arg)
{
	struct driverIdRep *rep = (struct driverIdRep *)arg;

	if (rep == NULL)
		return;

	if (rep->name) {
		free(rep->name);
		rep->name = NULL;
	}

	if (rep->organization)
	{
		free(rep->organization);
		rep->organization = NULL;
	}
}

static void
fend_localBulkUpload(void *arg)
{
}

static void
fend_event_data(void *arg)
{
	struct mediaData *data = (struct mediaData *)arg;

	if (data == NULL)
		return;

	if (data->data)
	{
		free(data->data);
		data->data = NULL;
	}
}

static void
fend_uplink_trans(void *arg)
{
	struct dataUpTrans *up = (struct dataUpTrans *)arg;
	if (up == NULL)
		return;

	if (up->data)
	{
		free(up->data);
		up->data = NULL;
	}
}

static void
fend_compress(void *arg)
{
	struct dataCompress *com = (struct dataCompress *)arg;

	if (com == NULL)
		return;

	if (com->data)
	{
		free(com->data);
		com->data = NULL;
	}
}


static int
fill_local_info(uint8_t *data, size_t size, struct endLocalInfo *info)
{
	if ((size != 28) || (data == NULL) || (info == NULL))
		return -1;
	
	size_t i = 0;
	/* 报警标志 */
	info->alarm = data[i] << 24 | data[i+1] << 16 | data[i+2] << 8 | data[i+3];
	i += 4;
	/* 状态 */
	info->status = data[i] << 24 | data[i+1] << 16 | data[i+2] << 8 | data[i+3];
	i += 4;
	/* 纬度 */
	info->latitude = data[i] << 24 | data[i+1] << 16 | data[i+2] << 8 | data[i+3];
	i += 4;
	/* 经度 */
	info->longitude = data[i] << 24 | data[i+1] << 16 | data[i+2] << 8 | data[i+3];
	i += 4;
	/* 高程 */
	info->elevation = data[i] << 8 | data[i+1];
	i += 2;
	/* 速度 */
	info->speed = data[i] << 8 | data[i+1];
	i += 2;
	/* 方向 */
	info->direction = data[i] << 8 | data[i+1];
	i += 2;
	/* 时间 */
	memcpy(info->timebcd, &data[i], 6);
	return 0;
}


static int
combine_pkg(int fd, struct msgRecv *r)
{
	if (r == NULL)
		return -1;
	size_t len = 0;
	uint8_t *data = NULL;
	size_t i;

	data = malloc(r->total * 1024);
	if (data == NULL)
		icar_die("Combine package had fatal error");
	memset(data, 0, r->total * 1024);

	for (i = 0; i < r->total; i++) {
		memcpy(&data[len], r->m[i].data, r->m[i].len);
		len += r->m[i].len;
	}

	icar_parse_msg(data, len, r->id, r->number, fd);

	return 0;
}

/* 
   对一个完整包的解析，当前包已经过处理，不含包头0x7e和包尾0x7e，且无校验码
	buf: 数据包的消息头和消息体
	size: 数据包的长度
	cient: 用于存储数据包解析后的有效数据
 */
int
icar_parse_pkg(uint8_t *buf, size_t size, struct msgclient *client)
{
	uint16_t id;
	uint16_t property;
	char number[20];
	uint16_t sequence;
	size_t i;
	size_t len;
	
	if ((buf == NULL) || (size < 12))
		return -1;

	i = id = property = 0;
	memset(number, 0, sizeof(number));
	sequence = 0;
	len = 0;

	id = buf[0] << 8  | buf[1];
	property = buf[2] << 8 | buf[3];
	len = MSG_LENGTH(property);

	i = 4;
	snprintf(number, sizeof(number), "%02x%02x%02x%02x%02x%02x",
			buf[i] & 0xff, buf[i+1] & 0xff, buf[i+2] & 0xff, 
			buf[i+3] & 0xff, buf[i+4] & 0xff, buf[i+5] & 0xff);
	i += 6;
	sequence = buf[i] << 8 | buf[i+1];
	i += 2;

	if (property & SUBPACKAGE) {
		if (size - 16 != len) {
			/* 回复一个平台通用消息或补传消息 */
			return -1;
		} else {
			uint16_t total;
			uint16_t index;
			struct msgRecv *r = NULL;
			time_t cur = time(NULL);

			total = buf[i] << 8 | buf[i+1];
			i += 2;
			index = buf[i] << 8 | buf[i+1];
			i += 2;
			if ((index > total) || (index == 0) || (total <= 1))
				return -1;

			for (r = client->msg; r != NULL; r = r->next) {
				if ((r->id == id) && (r->total == total)) {
					if (r->m[index-1].index == -1)
						break;
				}
			}

			if (r == NULL)
			{
				int k;
				r = calloc(1, sizeof(struct msgRecv) + total * sizeof(struct msgBody));
				if (r == NULL)
					icar_die("Package of data is parsed error");
				r->id = id;
				r->last = cur;
				r->total = total;
				r->cnt = 1;
				memcpy(r->number, number, 12);
				for (k = 0; k < total; k++)
					r->m[k].index = -1;
				r->m[index-1].len = len;
				memcpy(r->m[index-1].data, &buf[i], len);
				r->m[index-1].index = 1;
				r->m[index-1].sequence = sequence;

				r->next = client->msg;
				client->msg = r;

				return 0;
			} else {
				r->cnt++;
				r->m[index-1].sequence = sequence;
				r->m[index-1].index = 1;
				r->m[index-1].len = len;
				memcpy(r->m[index-1].data, &buf[i], len);

				if (r->cnt == r->total) {
					struct msgRecv * tmp = NULL;
					for (tmp = client->msg; tmp->next != NULL; tmp = tmp->next) 
						if (tmp->next == r)
						{
							tmp->next = r->next;
							combine_pkg(client->fd, r);
							free(r);
							break;
						}
				}

				return 0;

			}
		}

	} else {
		if (size - 12 != len) {
			/* 或者可以回复一个平台通用消息 */
			return -1;
		} else {
			uint8_t data[1024] = { 0 };
			memcpy(data, &buf[i], len);
			icar_parse_msg(data, len, id, number, client->fd);
		}
	}

	return 0;
}

/* 
   对分包消息组包后的完整消息体进行处理
	buf:	完整的消息体， 无消息头
	size:	消息体的长度(字节数)
	id:		消息ID
	number: 车机号码
	fd:		文件描述符(消息回复时会用到)
 */
void
icar_parse_msg(uint8_t *buf, size_t size, uint16_t id, const char *number, int fd)
{
	int i;
	void *arg = NULL;
	switch (id) {
	case ICAR_END_RESPONSE:
		{
			struct endResponse *res = calloc(1, sizeof(struct endResponse));
			if (res == NULL)
				return;
			arg = (void *)res;
		}
		break;
	case ICAR_END_REGISTER:
		{
			struct endRegister *reg = calloc(1, sizeof(struct endRegister));
			if (reg == NULL)
				return;
			arg = (void *)reg;
		}
		break;
	case ICAR_END_HEARTBEAT:
	case ICAR_END_UNREGISTER:
		break;
	case ICAR_END_AUTHENTICATE:
		{
			struct endAuth *auth = calloc(1, sizeof(struct endAuth));
			if (auth == NULL)
				return;
			arg = (void *)auth;
		}
		break;
	case ICAR_END_PARAM_RESPONSE:
		{
			int size = buf[0] & 0xff;
			struct param_list *param = calloc(1, sizeof(struct param_list) + size * sizeof(struct param_struct));
			if (param == NULL)
				return;

			arg = (void *)param;
		}
		break;
	case ICAR_END_ATTR_RES:
		{
			struct endAttr *attr = calloc(1, sizeof(struct endAttr));
			if (attr == NULL)
				return;
			arg = (void *)attr;
		}
		break;
	case ICAR_END_UPGRADE_NOTICE:
		{
			struct endUpdateNote *note = calloc(1, sizeof(struct endUpdateNote));
			if (note == NULL)
				return;

			arg = (void *)note;
		}
		break;
	case ICAR_END_LOCALINFO_REPORT:
		break;
	case ICAR_END_LOCALINFO_RESPONSE:
		{
			struct localInfoResponse *rep = calloc(1, sizeof(struct localInfoResponse));
			if (rep == NULL)
				return;
			arg = (void *)rep;
		}
		break;
	case ICAR_END_EVENT_REPORT:
		{
			uint8_t *id = calloc(1, sizeof(uint8_t));
			if (id == NULL)
				return;
			arg = (void *)id;
		}
		break;
	case ICAR_END_ASK_RESPONSE:
		{
			struct askRes *res = calloc(1, sizeof(struct askRes));
			if (res == NULL)
				return;

			arg = (void *)res;
		}
		break;
	case ICAR_END_INFO_HELPMENU_CANCLE:
		{
			struct infoBC *bc = calloc(1, sizeof(struct infoBC));
			if (bc == NULL)
				return;
			arg = (void *)bc;
		}
		break;
	case ICAR_END_VEICHLE_CTL_RESPONSE:
		{
			struct vehicleCtlRes *res = calloc(1, sizeof(struct vehicleCtlRes));
			if (res == NULL)
				return;
			arg = (void *)res;
		}
		break;
	case ICAR_END_DATA_RECORDER_UPLOAD:
		{
			struct recoderUpload *up = calloc(1, sizeof(struct recoderUpload));
			if (up == NULL)
				return;
			arg = (void *)up;
		}
		break;
	case ICAR_END_ELEC_WAYBILL_REPORT:
		{
			struct elecWaybillReport *elec = calloc(1, sizeof(struct elecWaybillReport));
			if (elec == NULL)
				return;
			arg = (void *)elec;
		}
		break;
	case ICAR_END_DRIVER_IDINFO_REPORT:
		{
			struct driverIdRep *rep = calloc(1, sizeof(struct driverIdRep));
			if (rep == NULL)
				return;
			arg = (void *)rep;
		}
		break;
	case ICAR_END_LOCALDATA_BULK_UPLOAD:
		break;
	case ICAR_END_CAN_DATA_UPLOAD:
		{
			int count = (buf[0] << 8 | buf[1]) & 0xffff;
			struct canUpload *up = calloc(1, sizeof(struct canUpload) + count * sizeof(struct can_data));
			if (up == NULL)
				return;
			arg = (void *)up;
		}
		break;
	case ICAR_END_MULTMEDIA_EVENT_UPLOAD:
		{
			struct mediaEvent *event = calloc(1, sizeof(struct mediaEvent));
			if (event == NULL)
				return;

			arg = (void *)event;
		}
		break;
	case ICAR_END_MULTMEDIA_DATA_UPLOAD:
		{
			struct mediaData *data = calloc(1, sizeof(struct mediaData));
			if (data == NULL)
				return;
			arg = (void *)data;
		}
		break;
	case ICAR_END_CAMERA_FILM_RESPONSE:
		{
			struct cameraFilmRes *res = calloc(1, sizeof(struct cameraFilmRes));
			if (res == NULL)
				return;
			arg = (void *)res;
		}
		break;
	case ICAR_END_STORE_MULTMEDIA_CHECK_RESPONSE:
		{
			int count;
			if (size < 4)
				return;
			count = (buf[3] << 8 | buf[4]) & 0xff;
			struct storeMediaRep *rep = calloc(1, sizeof(struct storeMediaRep) + count * sizeof(struct mediaRetrive));
			if (rep == NULL)
				return;
			arg = (void *)rep;
		}
		break;
	case ICAR_END_DATA_UPLINK_TRANSMISSON:
		{
			struct dataUpTrans *trans = calloc(1, sizeof(struct dataUpTrans));
			if (trans == NULL)
				return;
			arg = (void *)trans;
		}
		break;
	case ICAR_END_DATA_COMPRESS_REPORT:
		{
			struct dataCompress *com = calloc(1, sizeof(struct dataCompress));
			if (com == NULL)
				return;
			arg = (void *)com;
		}
		break;
	case ICAR_END_RSA_ENCRYPT:
		{
			struct endRsaEncrypt *rsa = calloc(1, sizeof(struct endRsaEncrypt));
			if (rsa == NULL)
				return;
			arg = (void *)rsa;
		}
		break;
	default:
		return;
	}

	for (i = 0; i < ARRAY_SIZE(msg_handles); i++)
	{
		if (id == msg_handles[i].id)
		{
			if (msg_handles[i].parse(buf, size, arg)) {
				if (arg) {
					free(arg);
					arg = NULL;
					return;
				}
			}
			msg_handles[i].handle(0, number, arg);
			if (msg_handles[i].free)
				msg_handles[i].free(arg);
		}
	}

	if (arg)
	{
		free(arg);
		arg = NULL;
	}
}
